#ifndef SERVER_H
#define SERVER_H

#include <QStringList>
#include <QTcpServer>
#include <QThread>
#include "ClientThread.h"

class GameMaster;

class Server : public QTcpServer
{
    Q_OBJECT

public:
    /*!
     * \brief The server's constructor.
     * \param _gm is a GameMaster object which allows the server to send messages back.
     */
    Server(QObject *parent = 0, GameMaster *_gm = 0);

    ~Server();

    /*!
     * \brief Returns a pointer to a clientHandle based on the socket descriptor's ID.
     * \param _id is the socket desciptor's ID to search for.
     */
    ClientHandle *getClient(int _id) const;

    /*!
     * \brief Returns a pointer to a clientHandle based on the client's name.
     * \param _name is a QString which will be used to search the client list.
     */
    ClientHandle *getClientByName(const QString &_name) const;

    /*!
     * \brief Returns a pointer to a clientThread based on the client's name.
     * \param _name is a QString which will be used to search the client list.
     */
    ClientThread *getClientThreadByName(const QString &_name);

    /*!
     * \brief Returns a pointer to a ClientHandle based on the client's direction.
     * \param _name is a QString which will be used to search the client list.
     */
    ClientHandle *getClientByDirection(int dir) const;

    /*!
     * \brief Returns a QList of every ClientHandle the server knows about.
     */
    QList<ClientHandle*> getClients() const;

    /*!
     * \brief Wrties a message to every client connected to the server.
     * \param _msg is a QString which contains the message to be sent to every client.
     */
    void writeToClients(const QString &_msg);

    /*!
     * \brief Sends a request to the relevant client asking for their bid.
     * \param client is a QString which represents the name of the client to send the request to.
     */
    void getBid( int, QString client);

    /*!
     * \brief Sends a message to the relevant client indicating that a bid has been made.
     * \param client is a QString which represents the name of the client to send the message to.
     * \param client_name is a QString which represents the name of the client who made the bid.
     * \param act is a QString which represents the bidding action.
     * \param count is an int which represents the card's value.
     * \param suit is a QString indicating which suit the bidder selected.
     */
    void sendBid( int, QString cname, QString client_name, QString act, int count, QString suit);

    /*!
     * \brief Sends a request to the relevant client asking for their move.
     * \param client_name is a QString which represents the name of the client to send the request to.
     */
    void getMove( int, QString client_name);

    /*!
     * \brief Sends a request to the relevant dummy client asking for their move.
     * \param client_name is a QString which represents the name of the client to send the request to.
     */
    void getDummyMove( int, QString client_name);

    /*!
     * \brief Sends a message to the relevant client indicating that a move has been made.
     * \param client_name is a QString which represents the name of the client to send the request to.
     * \param client_dir is an integer representation of the direction of the client (NSEW).
     * \param suit is a QString which represents the card's suit.
     * \param value is a QString which represents the card's value.
     */
    void sendMove( QString client_name, int client_dir, QString suit, QString value);

    /*!
     * \brief Sends an acknowledge message to the relevant client.
     * \param client_name is a QString which represents the name of the client to send the ack to.
     * \param success is an int which indidates whether the request was successful.
     * \param error_code is an int which indicates which error has occured.
     */
    void sendAcknowledge( int, QString client_name, int success, int error_code);

    /*!
     * \brief Sends a phase message to the relevant client.
     * \param client_name is a QString which represents the name of the client to send the message to.
     * \param phase is a QString indicating which phase to send.
     */
    void sendPhase( int, QString client_name, QString phase);

    /*!
     * \brief Sends a contract message to the relevant client.
     * \param client_name is a QString which represents the name of the client to send the message to.
     * \param trick_count is an int which represents the trick value the client selected.
     * \param trump_suit is a QString which represents the chosen trump suit.
     */
    void sendContract( QString client_name, int trick_count, QString trump_suit);

    /*!
     * \brief Sends a won update message to the relevant client.
     * \param client_to is a QString indicating which client to send the message to.
     * \param team is a QString indicating which team won.
     * \param note is a QString cotaining an additional information as per the communication protocol.
     */
    void sendWonUpdate( int, QString client_to, QString team, QString note);

    /*!
     * \brief Sends the dummy ID message to the relevant client.
     * \param QString client_name is the client to which the message must be sent.
     * \param QString dummy_name is the name of the dummy as identified by the dummy client.
     */
    void sendDummyID( int, QString client_name, QString dummy_name);

    /*!
     * \brief Sends an array of cards to the relevant client. Can be used to send them their hand (for example).
     * \param user_name is a QString indicating which client the message should be sent to.
     * \param cards is a QString containing a comma deliminated list of cards to send.
     * \param note is a QString containing any additional information as per the communication protocol.
     */
    void sendCardArray( int, QString user_name, QString cards, QString note);

    /*!
     * \brief Sends a score update message to the relevant client.
     * \param QString user_name is the name of the client who must receive the message.
     * \param QString wabove is the "we above" value.
     * \param QString wbelow is the "we below" value.
     * \param QString tabove is the "they above" value.
     * \param QString tbelow is the "they below" value.
     */
    void scoreUpdate( int, QString user_name, QString wabove, QString wbelow, QString tabove, QString tbelow);

    /*!
     * \brief Wrties a message to every client connected to the server.
     * \param json is a QJsonObject which cotains the json encoded message to send to every client.
     */
    void multicastMsg(QJsonObject json);

    QString getIP();

protected:
    void incomingConnection(qintptr socketDescriptor);

private:
    QStringList fortunes;

    QList<ClientThread*> clientList;

    GameMaster *gm;

    int num_clients;

    QStringList *directions;

    void writeJSON(QJsonObject json, ClientThread *client);

    QString functionFlag;

private slots:
    void processMsg(const QString &msg);

    void threadFinished(int threadId);

};

#endif // SERVER_H
